package com.hisicom.scqxspxcjc.common.file.serivce;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hisicom.scqxspxcjc.base.dao.BaseRepository;
import com.hisicom.scqxspxcjc.base.service.BaseService;
import com.hisicom.scqxspxcjc.common.file.bean.FileBean;
import com.hisicom.scqxspxcjc.common.file.exception.FileException;
import com.hisicom.scqxspxcjc.common.file.repository.FileRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static com.hisicom.scqxspxcjc.base.enums.ResultEnum.*;
import static com.hisicom.scqxspxcjc.common.file.util.MultipartFileToFile.getFileNameByType;

/**
 * @author zhonggls
 * @date 2020/4/21 17:18
 * @Explain
 */
@Service
@Slf4j
@Transactional
public class FileService implements BaseService<FileBean, String> {

    @Autowired
    FileRepository fileRepository;
    @Value("${file.basePath}")
    String basePath;


    @Override
    public BaseRepository<FileBean, String> getRepository() {
        return fileRepository;
    }

    /**
     * ************************************* 保存上传 **************************************
     */
    private String saveFile(MultipartFile file) {
        String name = UUID.fastUUID().toString();
        String pathsuffix = "/scenecheck/" + DateUtil.today() + "/";
        String path = basePath + pathsuffix;
        //file是一个临时文件，请求结束后自动删除
        //获取原始文件名
        String originalFilename = file.getOriginalFilename();
        //取文件名的后缀
        String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
        //使用uuid生成文件名，防止重复导致覆盖
        String fileName = UUID.randomUUID().toString() + substring;
        //创建一个目录对象
        File dir = new File(path);
        //判断目录是否存在
        if (!dir.exists()) {
            //目录不存在，则先创建
            dir.mkdirs();
        }
        try {
            //将临时文件转存到指定位置
            file.transferTo(new File(path + fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pathsuffix + fileName;
    }

    public void saveInfo(String businessId, String label, String name, MultipartFile file) {
        if (file == null) {
            log.error("上传文件时，文件不能为空");
            throw new FileException(ERROR_NOTNULL_FILE);
        }
        if (StrUtil.isBlank(label)) {
            throw new FileException("上传文件时，类型不能为空");
        }
        //保存文件
        String path = saveFile(file);
        saveFileBean(null, businessId, name, path, label, null);
    }

    private FileBean saveFileBean(String id, String businessId, String name, String path, String label, String sort) {
        if (StrUtil.isNotBlank(id)) {
            FileBean fileBean = getById(id);
            if (StrUtil.isNotBlank(path) && !path.equals(fileBean.getPath())) {
                delPath(fileBean);
                fileBean.setPath(path);
            }
            if (StrUtil.isNotBlank(name) && !name.equals(fileBean.getName())) {
                fileBean.setName(name);
            }
            if (StrUtil.isNotBlank(label) && !label.equals(fileBean.getLabel())) {
                fileBean.setLabel(label);
            }
            if (StrUtil.isNotBlank(sort) && !sort.equals(fileBean.getSort())) {
                fileBean.setSort(sort);
            }
            return fileRepository.save(fileBean);
        } else {
            FileBean file1 = new FileBean();
            if (StrUtil.isBlank(path)) {
                throw new FileException(ERROR_NOTNULL_FILE_PATH);
            }
            file1.setPath(path);
            if (StrUtil.isNotBlank(name)) {
                file1.setName(name);
            }
            if (StrUtil.isNotBlank(businessId)) {
                file1.setFkBusinessId(businessId);
                file1.setStatus("1");//0未绑定业务数据
            } else {
                file1.setStatus("0");//0未绑定业务数据
            }
            if (StrUtil.isNotBlank(label)) {
                file1.setLabel(label);//设置文件标签
            }
            if (StrUtil.isNotBlank(sort)) {
                file1.setSort(sort);//设置文件序号
            }
            return fileRepository.save(file1);
        }
    }


    /**
     * 保存业务id
     *
     * @param fileIds    文件id
     * @param businessId 业务id
     */
    public void saveBusinessId(String fileIds, String businessId) {
        if (StrUtil.isBlank(fileIds)) {
            log.error("保存文件业务id时，文件id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_FILEID);
        }
        if (StrUtil.isBlank(businessId)) {
            log.error("保存文件业务id时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        String[] fileIdList = fileIds.split(",");
        for (String fileId : fileIdList) {
            Optional<FileBean> optional = fileRepository.findById(fileId);
            if (!optional.isPresent()) {
                log.error("保存业务id时，文件获取失败");
                throw new FileException(ERROR_NOTFOUND_FILE);
            }
            FileBean fileBean = optional.get();
            fileBean.setFkBusinessId(businessId);
            fileBean.setStatus("1");//状态` 1.已绑定业务数据，0未绑定业务数据',
            fileRepository.save(fileBean);
        }
    }

    /**
     * 自动生成文件名
     *
     * @param file 文件
     * @return 文件名
     */
    public String getNewName(MultipartFile file) {
//        String name = getUUID32();
        String name = String.valueOf(System.currentTimeMillis());
        String fileName = file.getOriginalFilename();
        if (StrUtil.isNotBlank(fileName)) {
            int index = fileName.lastIndexOf(".");//获取第几位是.
            if (index != -1) {
                return name + fileName.substring(index);
            } else {
                return name + getFileNameByType(file);
            }
        } else {
            return name + getFileNameByType(file);
        }
    }

    /**
     * ************************************* 查找 **************************************
     */


    /**
     * 查找文件
     *
     * @param fileId 业务id
     * @return
     */
    public FileBean findById(String fileId) {
        if (StrUtil.isBlank(fileId)) {
            log.error("查找文件业务id时，id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_FILEID);
        }
        Optional<FileBean> optional = fileRepository.findById(fileId);
        if (!optional.isPresent()) {
            log.error("查找文件时，文件获取失败");
            throw new FileException(ERROR_NOTFOUND_FILE);
        }
        return optional.get();
    }

    /**
     * 查找文件
     *
     * @param businessId 业务id
     * @return
     */
    public List<FileBean> findByFkBusinessId(String businessId) {
        if (StrUtil.isBlank(businessId)) {
            log.error("查找文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        return fileRepository.findByFkBusinessIdOrderByLabelAscSortAsc(businessId);
    }

    /**
     * 获取完整路径
     *
     * @param businessId
     * @return
     */
    public List<FileBean> findByFkBusinessId1(String businessId) {
        if (StrUtil.isBlank(businessId)) {
            log.error("查找文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        List<FileBean> list = fileRepository.findByFkBusinessIdOrderByLabelAscSortAsc(businessId);
        List<FileBean> backlist = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(list)) {
            for (FileBean fileBean : list) {
                FileBean fileBean1 = new FileBean();
                BeanUtils.copyProperties(fileBean1, fileBean);
                fileBean1.setPath(basePath + fileBean.getPath());
                backlist.add(fileBean1);
            }
        }
        return backlist;
    }

    /**
     * 查找文件
     *
     * @param businessId 业务id
     * @param label      标签
     * @return
     */
    public List<FileBean> findByFkBusinessIdAndLabel(String businessId, String label) {
        if (StrUtil.isBlank(businessId)) {
            log.error("查找文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        if (StrUtil.isBlank(label)) {
            return findByFkBusinessId(businessId);
        }
        List<FileBean> list = fileRepository.findByFkBusinessIdAndLabelOrderBySortAsc(businessId, label);
        return list;
    }

    /**
     * 查找文件
     *
     * @param businessId 业务id
     * @param label      标签
     * @param sort       序号
     * @return
     */
    public List<FileBean> findByFkBusinessIdAndLabelAndSort(String businessId, String label, String sort) {
        if (StrUtil.isBlank(businessId)) {
            log.error("查找文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        if (StrUtil.isBlank(label)) {
            return findByFkBusinessId(businessId);
        }
        if (StrUtil.isBlank(sort)) {
            return findByFkBusinessIdAndLabel(businessId, label);
        }
        List<FileBean> list = fileRepository.findByFkBusinessIdAndLabelAndSort(businessId, label, sort);
        return list;
    }

    /**
     * ************************************* 删除 **************************************
     */

    /**
     * 删除文件
     *
     * @param fileId 文件id
     */
    public void deleteById(String fileId) {
        if (StrUtil.isBlank(fileId)) {
            log.error("删除文件时，文件id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_FILEID);
        }
        //获取文件
        FileBean fileBean = findById(fileId);
        delPath(fileBean);//删除文件
        fileRepository.deleteById(fileId);
    }

    /**
     * 删除文件
     *
     * @param businessId 业务id
     */
    public void deleteByFkBusinessId(String businessId) {
        if (StrUtil.isBlank(businessId)) {
            log.error("删除文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        delPath(findByFkBusinessId(businessId));//删除文件
        fileRepository.deleteByFkBusinessId(businessId);
    }

    /**
     * 删除文件
     *
     * @param businessId 业务id
     * @param label      文件标签
     */
    public void deleteByFkBusinessIdAndLabel(String businessId, String label) {
        if (StrUtil.isBlank(businessId)) {
            log.error("删除文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        if (StrUtil.isBlank(label)) {
            log.error("删除文件时，文件标签不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_LABEL);
        }
        delPath(findByFkBusinessIdAndLabel(businessId, label));//删除文件
        fileRepository.deleteByFkBusinessIdAndLabel(businessId, label);
    }

    /**
     * 删除文件
     *
     * @param businessId 业务id
     * @param label      文件标签
     * @param sort       文件序号
     */
    public void deleteByFkBusinessIdAndLabelAndSort(String businessId, String label, String sort) {
        if (StrUtil.isBlank(businessId)) {
            log.error("删除文件时，业务id不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_BUSINESSID);
        }
        if (StrUtil.isBlank(label)) {
            log.error("删除文件时，文件标签不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_LABEL);
        }
        if (StrUtil.isBlank(sort)) {
            log.error("删除文件时，文件序号不能为空！");
            throw new FileException(ERROR_NOTNULL_FILE_SORT);
        }
        delPath(findByFkBusinessIdAndLabelAndSort(businessId, label, sort));//删除文件
        fileRepository.deleteByFkBusinessIdAndLabelAndSort(businessId, label, sort);
    }

    /**
     * 删除文件
     *
     * @param status 状态
     * @param date   时间
     */
    public void deleteByStatusAndCreateTimeBefore(String status, Date date) {
        fileRepository.deleteByStatusAndCreateTimeBefore(status, date);
    }

    private void delPath(FileBean fileBean) {
        String pathsuffix = fileBean.getPath();
        String path = basePath + pathsuffix;
        if (StrUtil.isNotBlank(path)) {
            File file = new File(path);
            if (file.delete()) {
                System.out.println("文件删除成功！");
            } else {
                System.out.println("文件删除失败。");
            }
        }
    }

    private void delPath(List<FileBean> fileBeans) {
        if (ObjectUtil.isNotEmpty(fileBeans)) {
            Iterator<FileBean> fileBean = fileBeans.iterator();
            while (fileBean.hasNext()) {
                String pathsuffix = fileBean.next().getPath();
                String path = basePath + pathsuffix;
                if (StrUtil.isNotBlank(path)) {
                    File file = new File(path);
                    if (file.delete()) {
                        System.out.println("文件删除成功！");
                    } else {
                        System.out.println("文件删除失败。");
                    }
                }
            }
        }

    }
}
